import json
import logging
from django.db import transaction
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import get_user_model
from tag.models import Text
from .models import KnowledgeGraph, Entity, Relationship
import requests
import re

logger = logging.getLogger(__name__)
User = get_user_model()

# NVIDIA API 配置（直接内联配置）
NVIDIA_CONFIG = {
    "API_ENDPOINT": "https://integrate.api.nvidia.com/v1/chat/completions",
    "MODEL_NAME": "deepseek-ai/deepseek-r1",
    "API_KEY": "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",
    "TIMEOUT": 30  # 合理超时时间
}

KG_PROMPT = r'''请根据以下文本生成详细的知识图谱，要求：
1. 输出严格JSON格式，包含entities和relationships两个数组,直接输出JSON格式，不要其余任何多余字段，如JSON，‘’‘
2. 实体需标注类型(PERSON/ORG/LOC/EVENT/CONCEPT)
3. 关系需标注类型(BELONG_TO/LOCATED_IN/PART_OF/CAUSE/SIMILAR)
4. 每个实体必须包含name、type和description字段
5. 每个关系必须包含source、target、type和weight(0-1)
6. 注意JSON 的键需要用双引号，JSON 的标准要求键名必须用双引号括起来，返回正确的JOSN格式
示例格式：
{{
    "entities": [
        {{"name": "北京", "type": "LOC", "description": "中国首都"}},
        {{"name": "故宫", "type": "ORG", "description": "明清皇家宫殿"}}
    ],
    "relationships": [
        {{"source": "故宫", "target": "北京", "type": "LOCATED_IN", "weight": 0.9}}
    ]
}}

待分析文本：{text}'''


# def call_kg_api(text):
#     """调用NVIDIA知识图谱API"""
#     try:
#         response = requests.post(
#             NVIDIA_CONFIG["API_ENDPOINT"],
#             headers={
#                 "Authorization": f"Bearer {NVIDIA_CONFIG['API_KEY']}",
#                 "Content-Type": "application/json"
#             },
#             json={
#                 "model": NVIDIA_CONFIG["MODEL_NAME"],
#                 "messages": [{
#                     "role": "user",
#                     "content": KG_PROMPT.format(text=text)
#                 }],
#                 "temperature": 0.3,
#                 "max_tokens": 2000,
#                 "response_format": {"type": "json_object"}
#             },
#             timeout=NVIDIA_CONFIG["TIMEOUT"]
#         )
#         response.raise_for_status()
#         return response.json()['choices'][0]['message']['content']
#     except Exception as e:
#         logger.error(f"API调用失败: {str(e)}", exc_info=True)
#         return None

def call_kg_api(text):
    """调用知识图谱API"""
    # print(f"[DEBUG] 正在调用API端点：{NVIDIA_CONFIG['API_ENDPOINT']}")
    # print(f"[DEBUG] 使用模型：{NVIDIA_CONFIG['MODEL_NAME']}")
    # print(f"[DEBUG] API密钥前6位：{NVIDIA_CONFIG['API_KEY'][:6]}...")

    try:
        # 构造请求体时使用原始字符串
        payload = {
            "model": NVIDIA_CONFIG["MODEL_NAME"],
            "messages": [{
                "role": "user",
                "content": KG_PROMPT.format(text=text.replace("{", "{{").replace("}", "}}"))
            }],
            "temperature": 0.3,
            # "max_tokens": ,
            "response_format": {"type": "json_object"}
        }

        # 调试打印请求内容
        # print("[DEBUG] 完整请求体：", json.dumps(payload, indent=2, ensure_ascii=False))

        response = requests.post(
            NVIDIA_CONFIG["API_ENDPOINT"],
            headers={
                "Authorization": f"Bearer {NVIDIA_CONFIG['API_KEY']}",
                "Content-Type": "application/json"
            },
            json=payload,
            # timeout=NVIDIA_CONFIG["TIMEOUT"]
        )

        # 记录原始响应用于调试
        # raw_response = response.text
        # print(f"[DEBUG] 原始响应内容：\n{raw_response[:500]}...")  # 截断长响应

        response.raise_for_status()

        # 解析响应内容
        response_data = response.json()
        ai_content = response_data['choices'][0]['message']['content']

        # 清理响应内容
        clean_content = re.sub(r'<think>.*?</think>', '', ai_content, flags=re.DOTALL).strip()
        # print(f"[DEBUG] 清理后内容：\n{clean_content}")
        return clean_content

        # 转换为JSON对象
        # try:
        #     kg_json = json.loads(clean_content)
        #     print("[DEBUG] JSON解析成功")
        #     return kg_json
        # except json.JSONDecodeError as e:
        #     logger.error(f"JSON解析失败：{str(e)}")
        #     logger.error(f"无效内容：{clean_content}")
        #     return None

    except requests.exceptions.HTTPError as e:
        error_info = {
            "status_code": e.response.status_code,
            "reason": e.response.reason,
            "headers": dict(e.response.headers),
            "response_body": e.response.text[:1000]
        }
        logger.error(f"HTTP错误：{json.dumps(error_info, indent=2)}")
        return None
    except Exception as e:
        logger.error(f"API调用异常：{str(e)}", exc_info=True)
        return None

# @csrf_exempt
# @transaction.atomic
# def generate_knowledge_graph(request):
#     """生成知识图谱接口"""
#     if request.method == 'POST':
#         try:
#             # 解析并验证请求数据
#             data = json.loads(request.body)
#             text_id = data['text_id']  # 必需字段
#             graph_name = data.get('name', '未命名图谱')
#
#             # 获取当前用户
#             user = request.user if request.user.is_authenticated else None
#
#             # 获取关联文本
#             try:
#                 text = Text.objects.get(id=text_id)
#             except Text.DoesNotExist:
#                 return JsonResponse({'status': 'error', 'message': '文本不存在'}, status=404)
#
#             # 调用AI生成图谱
#             kg_json = call_kg_api(text.content)
#             if not kg_json:
#                 return JsonResponse({'status': 'error', 'message': '知识图谱生成失败'}, status=500)
#
#             try:
#                 kg_data = json.loads(kg_json)
#             except json.JSONDecodeError:
#                 logger.error("API返回非法JSON数据")
#                 return JsonResponse({'status': 'error', 'message': '数据解析失败'}, status=500)
#
#             # 创建知识图谱记录
#             graph = KnowledgeGraph.objects.create(
#                 name=graph_name,
#                 original_text=text,
#                 creator=user,
#                 raw_data=kg_data
#             )
#
#             # 处理实体和关系
#             entity_map = {}
#             for entity in kg_data.get('entities', []):
#                 # 数据验证
#                 if not all(key in entity for key in ['name', 'type']):
#                     logger.warning(f"非法实体数据: {entity}")
#                     continue
#
#                 e = Entity.objects.create(
#                     name=entity['name'][:100],  # 确保不超过字段长度
#                     type=entity['type'],
#                     description=entity.get('description', '')[:500],
#                     graph=graph,
#                     properties=entity.get('properties', {})
#                 )
#                 entity_map[entity['name']] = e
#
#             for rel in kg_data.get('relationships', []):
#                 # 关系验证
#                 required_fields = ['source', 'target', 'type']
#                 if not all(field in rel for field in required_fields):
#                     logger.warning(f"非法关系数据: {rel}")
#                     continue
#
#                 try:
#                     Relationship.objects.create(
#                         source=entity_map[rel['source']],
#                         target=entity_map[rel['target']],
#                         type=rel['type'],
#                         weight=min(max(rel.get('weight', 1.0), 5.0),  # 限制权重范围
#                                    graph=graph
#                                    )
#                 except KeyError as e:
#                     logger.error(f"关联实体不存在: {str(e)}")
#
#             return JsonResponse({
#                 'status': 'success',
#                 'graph_id': graph.id,
#                 'entity_count': len(entity_map),
#                 'relationship_count': Relationship.objects.filter(graph=graph).count()
#             })
#
#         except json.JSONDecodeError:
#             return JsonResponse({'status': 'error', 'message': '非法JSON请求'}, status=400)
#         except KeyError as e:
#             logger.error(f"请求参数缺失: {str(e)}")
#             return JsonResponse({'status': 'error', 'message': '缺少必要参数'}, status=400)
#         except Exception as e:
#             logger.error(f"系统错误: {str(e)}", exc_info=True)
#             return JsonResponse({'status': 'error', 'message': '服务器内部错误'}, status=500)
#
#     return JsonResponse({'status': 'error', 'message': '仅支持POST请求'}, status=405)

@csrf_exempt
@transaction.atomic
def generate_knowledge_graph(request):
    """生成知识图谱接口"""
    if request.method == 'POST':
        try:
            # 解析并验证请求数据
            data = json.loads(request.body)
            text_id = data['text_id']  # 必需字段
            graph_name = data.get('name', '未命名图谱')

            # 获取当前用户
            user = request.user if request.user.is_authenticated else None

            # 获取关联文本
            try:
                text = Text.objects.get(id=text_id)
            except Text.DoesNotExist:
                return JsonResponse({'status': 'error', 'message': '文本不存在'}, status=404)

            # 调用AI生成图谱
            kg_json = call_kg_api(text.content)
            if not kg_json:
                return JsonResponse({'status': 'error', 'message': '知识图谱生成失败'}, status=500)

            try:
                kg_data = json.loads(kg_json)
                # print(f"[DEBUG] 清理后内容：\n{kg_data}")
            except json.JSONDecodeError:
                logger.error("API返回非法JSON数据")
                return JsonResponse({'status': 'error', 'message': '数据解析失败'}, status=500)

            # 创建知识图谱记录
            graph = KnowledgeGraph.objects.create(
                name=graph_name,
                original_text=text,
                creator=user,
                raw_data=kg_data
            )

            # 处理实体和关系
            entity_map = {}
            for entity in kg_data.get('entities', []):
                # 数据验证
                if not all(key in entity for key in ['name', 'type']):
                    logger.warning(f"非法实体数据: {entity}")
                    continue

                e = Entity.objects.create(
                    name=entity['name'][:100],  # 确保不超过字段长度
                    type=entity['type'],
                    description=entity.get('description', '')[:500],
                    graph=graph,
                    properties=entity.get('properties', {})
                )
                entity_map[entity['name']] = e

            for rel in kg_data.get('relationships', []):
                # 关系验证
                required_fields = ['source', 'target', 'type']
                if not all(field in rel for field in required_fields):
                    logger.warning(f"非法关系数据: {rel}")
                    continue

                try:
                    Relationship.objects.create(
                        source=entity_map[rel['source']],
                        target=entity_map[rel['target']],
                        type=rel['type'],
                        # 修正权重范围为0.0-1.0
                        weight=min(max(rel.get('weight', 1.0), 0.0), 1.0),
                        graph=graph
                    )
                except KeyError as e:
                    logger.error(f"关联实体不存在: {str(e)}")

            return JsonResponse({
                'status': 'success',
                'graph_id': graph.id,
                'entity_count': len(entity_map),
                'relationship_count': Relationship.objects.filter(graph=graph).count()
            })

        except json.JSONDecodeError:
            return JsonResponse({'status': 'error', 'message': '非法JSON请求'}, status=400)
        except KeyError as e:
            logger.error(f"请求参数缺失: {str(e)}")
            return JsonResponse({'status': 'error', 'message': '缺少必要参数'}, status=400)
        except Exception as e:
            logger.error(f"系统错误: {str(e)}", exc_info=True)
            return JsonResponse({'status': 'error', 'message': '服务器内部错误'}, status=500)

    return JsonResponse({'status': 'error', 'message': '仅支持POST请求'}, status=405)